package weka.clusterers;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Scanner;
import java.util.HashSet;
import java.util.Set;

//import com.sun.org.apache.xalan.internal.xsltc.runtime.Hashtable;

public class Groups {

	 public static int[][] createIntMatrix(int rows,int cols) {
		    int[][] matrix = new int[rows][cols];
		    for (int i=0 ; i < rows ; i++){
		    	for  (int j=0 ; j < cols ; j++){
		    		matrix[i][j]=0;
	            }
		    }
		    return matrix;
	    }
	 
	 public static Double[][] createDoubleMatrix(int rows,int cols) {
		    Double [][] matrix = new Double[rows][cols];
		    for (int i=0 ; i < rows ; i++){
		    	for  (int j=0 ; j < cols ; j++){
		    		matrix[i][j]=0.0;
	            }
		    }
		    return matrix;
	    }
	 
	 public static String[][] createStringMatrix(int rows,int cols) {
		 String [][] matrix = new String[rows][cols];
		 for (int i=0 ; i < rows ; i++){
		    	for  (int j=0 ; j < cols ; j++){
		    		matrix[i][j]="";
	            }
		    }
		    return matrix;
	    }
	 
	 public static String[] createNames(int dim,int typeName) {
		 String[]  matrix = new String[dim+1];
		 
		 if (dim<100) {
			 for  (int j=0 ; j < dim ; j++){
		    		matrix[j]="Person "+(j+1);
	            }
			 matrix[dim]="NotInFrame";
		 }
		 else { // Europe Movies
			 if (typeName==101) {
				 matrix[0]="Wdress";
				 matrix[1]="MBlackPants";
				 matrix[2]="MShorts";
				 matrix[3]="Wjeans&white";
				 matrix[4]="Wyellow";
				 matrix[5]="WwhiteSkirt";
				 matrix[6]="NotInFrame";
				 }
				 
				 if (typeName==102) {
				 
				 matrix[0]="Striped";
				 matrix[1]="Green";
				 matrix[2]="White";
				 matrix[3]="Shorts";
				 matrix[4]="Gray ";
				 matrix[5]="Dress";
				 matrix[6]="NotInFrame";
				 
				 }
		 }		 
		 
/*		 for (int i=0;i<dim;i++){
			 System.out.println(matrix[i]);
		 }   
*/			 
		 return matrix;
	    }
	 
	 
	 public static String getHeader(int typeName){
		 String header="frame Number;";
		 if (typeName<100) {
			 for  (int j=0 ; j < typeName ; j++){
		    		header=header+"Person "+(j+1)+";";
	         }
//			 matrix[dim]="NotInFrame";
		 }
		 else { // Europe Movies
			 if (typeName==101) {
				 header="frame Number;Woman in DRESS;Man in BLACK pants;Man in SHORTS;Woman in Jeans and White;Woman in Yellow;Woman in White skirt";
			 }
			 if (typeName==102) {
				 header="Frame Number;Man in STRIPED  shirt;Man in GREEN shirt;Women in WHITE;Women in SHORTS;Women in GRAY;Women in short DRESS"; 
			 }
		 }
		 return header;

	 }
	 
	 
	 public static int[][] Initialize(int[][] matrix,int rows,int cols){
		 for (int i=0 ; i < rows ; i++){
		    	for  (int j=0 ; j < cols ; j++){
		    		matrix[i][j]=-2;
	            }
		    }
		  return matrix;  
	 }
	 
	 public static int comb2(int num){
		 int numerator=num-2;
		 int total=1;
		 for (int i=num;i>numerator;i--){
			 total=total*i;
		 }
		 return total/2;
	 }
	    
	 public  static void printMatrix(int[][] matrix,int rows,int cols) {
	    for (int i=0 ; i < rows ; i++){
	    	System.out.println();
	    
	    	for  (int j=0 ; j < cols ; j++){
	    		System.out.print(matrix[i][j]+" ");
            }
	    }
	    System.out.println();
	 }
	 
	 public  static void printMatrix(Double[][] matrix,int rows,int cols) {
		    for (int i=0 ; i < rows ; i++){
		    	System.out.println();
		    
		    	for  (int j=0 ; j < cols ; j++){
		    		System.out.print(matrix[i][j]+" ");
	            }
		    }
		    System.out.println();
		 }
	 
	 public  static void printMatrix(String[][] matrix,int rows,int cols){
		 for (int i=0 ; i < rows ; i++){
		    	System.out.println();
		    
		    	for  (int j=0 ; j < cols ; j++){
		    		System.out.print(matrix[i][j]+" ");
	            }
		    }
		    System.out.println();
	 }
	 
	 public static int max(int[] t) {
		    int maximum = t[0];   // start with the first value
		    for (int i=1; i<t.length; i++) {
		        if (t[i] > maximum) {
		            maximum = t[i];   // new maximum
		        }
		    }
		    return maximum;
		}//end method max
	 
	 
	 public static int min(int[] t) {
		    int min = t[0];   // start with the first value
		    for (int i=1; i<t.length; i++) {
		        if (t[i] < min) {
		            min = t[i];   // new minimun
		        }
		    }
		    return min;
		}//end method min
	 
	 
	 
	 public static int minGreatherThanNegative2(int[] t) {
		    int min = t[0];   // start with the first value
		    for (int i=1; i<t.length; i++) {
		        if (t[i] < min && t[i]!=-2) {
		            min = t[i];   // new minimun
		        }
		    }
		    return min;
		}//end method min
	 
	 
	 public static Double minGreatherThanZero(Double[] t) {
		    Double min = t[0];   // start with the first value
		    for (int i=1; i<t.length; i++) {
		        if (t[i] < min && t[i]!=0) {
		            min = t[i];   // new minimun
		        }
		    }
		    return min;
		}//end method min
	 
	 public static Double min(Double[] t) {
		    Double min = t[0];   // start with the first value
		    for (int i=1; i<t.length; i++) {
		        if (t[i] < min) {
		            min = t[i];   // new minimun
		        }
		    }
		    return min;
		}//end method min
	 
	 public static Set findGroupsFrame(int[] t){
	
		 Set groups = new HashSet();

		for (int i=0; i<t.length; i++) {
			 	Set group = new HashSet();
				if (t[i]==-1) {
					group.add(i);
					groups.add(group);
				}
				if (t[i]==-2){
					groups.add(group);  // empty
				}	
		}
		 
		 
		 int totalGroups = max(t); 
		 int minGroup=min(t); 
		 for (int g=0; g<=totalGroups;g++){
			Set group = new HashSet(); 					
			for (int i=0; i<t.length; i++) {
				if (t[i]==g) {
					group.add(i);
				}
			}
			groups.add(group);
		}

		 return groups;
	 }
	 
	 
	 public static Set findGroupsFrame2(int[] t){

		 Set groups = new HashSet();
		 int totalGroups = max(t); 
		 int minGroup=min(t); 
		 for (int g=minGroup; g<=totalGroups;g++){
			 if (g>-2){
				Set group = new HashSet(); 
				for (int i=0; i<t.length; i++) {
					if (t[i]==g) {
						group.add(i);
					}
				}
		 	
				groups.add(group);
			 }
			 
		 }
		 return groups;
	 }
	 
	 public static Set findUniqueGroups(int[][] matrix,int totalFrames){
		 Set groups= new HashSet();
//		 Set temp=new HashSet();
	     for (int f=0; f<totalFrames;f++){
//	    	 temp=findGroupsFrame(matrix[f]);
//	    	 if (!temp.isEmpty()) {
		         Object[] all =findGroupsFrame(matrix[f]).toArray();
		         for (int j=0; j<all.length;j++){
		         	groups.add(all[j]);
		         }
//	    	 }
	     }
	     return groups;
	 }
	 
	 
	 public static int[][] setPersonOutOfFrame(int[][] matrix,int[][] newMatrix,int row,int cols,int id){
		 for (int j=0;j<cols;j++){
			 if (matrix[row][j]==-2) {
				 newMatrix[row][j]=id;
			 }
		 }
		 return newMatrix;
		 
	 }
	 
	 
	 
	 public static int findIdGroup(Set uniqueGroups,Object all2) {
	     Object[] all = uniqueGroups.toArray();
	     for (int j=0; j<all.length;j++){
	     	if (all[j].equals(all2))
	     		return j;
	     }
	     return -1;
	 }
	 
	 public static Object findGroup(Set uniqueGroups, int id) {
		 Object[] all = uniqueGroups.toArray();
		 return all[id];
	 }
	 
	 
	 public static int[][] setIdGroups(int[][] matrix,Set uniqueGroups,int totalFrames,int totalPersons){
		 Set group= new HashSet();
		 Set tempG= new HashSet();
		 int newMatrix[][]=Groups.createIntMatrix(totalFrames,totalPersons);
		 int id;
		 
	     for (int f=0; f<totalFrames;f++){
//	    	 tempG=findGroupsFrame(matrix[f]);
//	    	 if (!tempG.isEmpty()) {
	    		 Object[] all = findGroupsFrame(matrix[f]).toArray();
		         for (int j=0; j<all.length;j++){
	
		        	 id=findIdGroup(uniqueGroups,all[j]);
	//	         	 System.out.println(all[j]+"  "+id);
		         	 group=(Set) all[j];
		         	 if (! group.isEmpty()) {

			         	Object[]  temp= group.toArray();
			         	for (int k=0; k<temp.length;k++){
		//	         		System.out.println(temp[k]+"  "+id);
			         		int person=(Integer) temp[k];
			         		newMatrix[f][person]=id;
			         	}
		         	 }
		         	 else {
		         		newMatrix=setPersonOutOfFrame(matrix,newMatrix,f,totalPersons,id);
		         	 }
		         	 
		         }
//	    	 }
	     }
//	     printMatrix(newMatrix,totalFrames,totalPersons);
	     return newMatrix;
	 }
	 
	 public static String getDescriptionGroup(Set uniqueGroups,int id,String desc,int totalPersons,int typeName) {
		 Set group= new HashSet();
		 Set descGroup= new HashSet();
		 String[] c=createNames(totalPersons,typeName);
		 String result;
/*		 for (int i=0;i<=totalPersons;i++){
			 System.out.println(c[i]);
		 }  */ 

		 Object[] all =uniqueGroups.toArray();
		 group=(Set) all[id];
     	 if (! group.isEmpty()) {

         	Object[]  temp= group.toArray();

         	for (int k=0; k<temp.length;k++){
//	         		System.out.println(temp[k]+"  "+id);
         		int person=(Integer) temp[k];
         		descGroup.add(c[person]);
         	}
         	result=desc+":"+descGroup;
     	 }
     	 else {
     		descGroup.add(c[totalPersons]);
     		result="-1:"+descGroup;
     	 }
     	 return result;
	 }
	 
     public  static Hashtable initializeGroupsdiffId(Set uniqueGroups) {
     	Hashtable idGroupsDiff = new Hashtable();
	        Object[] all =uniqueGroups.toArray();
	        for (int j=0; j<all.length;j++){
	        	idGroupsDiff.put(all[j], new Integer(1)); 
	        }
	        return idGroupsDiff;
     }
     
     public  static Hashtable putGroupsdiffId(Hashtable idGroupsDiff,Object obj) {

    	 int value=(Integer) idGroupsDiff.get(obj);
 	     idGroupsDiff.put(obj,value+1); 
 	     return idGroupsDiff;
 	     
      }
     
	 public static String[][] updateGroup(int[][] matrix,String[][]newMatrix,int row,int cols,int group,Hashtable groupsDiffId,Set uniqueGroups ){
		 for (int j=0;j<cols;j++){
			 if (matrix[row-1][j]==group) {
				 Object obj=findGroup(uniqueGroups,matrix[row][j]);
    			 String newVal=Integer.toString(matrix[row][j]) +"-"+groupsDiffId.get(obj);
				 newMatrix[row][j]=newVal;
			 }
		 }
		 return newMatrix;
	 }
     
     
     public  static void printGroupsdiffId(Hashtable idGroupsDiff) {
	     Enumeration groups;
	     
	     
	     // Show all groups and their respective number  in hash table.
	    groups = idGroupsDiff.keys();
		while(groups.hasMoreElements()) {
				Object	obt=groups.nextElement();
				System.out.println(obt + ": " +idGroupsDiff.get(obt));
			}
     }
     
     
     public  static String [][] setIdGroupsDiffId(int [][]matrix, Set uniqueGroups,int totalFrames,int totalPersons){
    	 
    	 Hashtable groupsDiffId=initializeGroupsdiffId(uniqueGroups);
    	 Object[] all =uniqueGroups.toArray();
		 Set group= new HashSet();
		 Set tempG= new HashSet();
		 Object obj;
		 String [][] newMatrix=Groups.createStringMatrix(totalFrames,totalPersons);
		 int id;
		 for (int p=0;p<totalPersons;p++){
			 obj=findGroup(uniqueGroups,matrix[0][p]);
			 newMatrix[0][p]=Integer.toString(matrix[0][p]) +"-"+groupsDiffId.get(obj);
		 }
		 
	    for (int f=1; f<totalFrames;f++){
	         for (int p=0; p<totalPersons;p++){
	        	 if (newMatrix[f][p].isEmpty()) {
		        	 if (matrix[f][p]==matrix[f-1][p]){
		        		 obj=findGroup(uniqueGroups,matrix[f][p]);
		    			 newMatrix[f][p]=Integer.toString(matrix[f][p]) +"-"+groupsDiffId.get(obj);
		        	 }
		        	 else { 
	        			 obj=findGroup(uniqueGroups,matrix[f-1][p]);
	        			 groupsDiffId=putGroupsdiffId(groupsDiffId, obj); // increase group number
	        			
	        			 newMatrix=updateGroup(matrix,newMatrix,f,totalPersons,matrix[f-1][p],groupsDiffId,uniqueGroups);
		        	 }
	        	 }
	         }
     }
//     printMatrix(newMatrix,totalFrames,totalPersons);
     return newMatrix;
 }

     
	 
	 public  static void printDescGroups(Set  uniqueGroups,int totalPersons,int typeName) {
	     for (int i=0; i<uniqueGroups.size();i++) {
	     	
	     	System.out.println(getDescriptionGroup( uniqueGroups, i,""+i, totalPersons, typeName));
	     }	 
	 }

	 public  static void printAllFrames(int[][] matrix,int totalFrames,int totalPersons,Set uniqueGroups,int typeName) {
	    System.out.println();
		 printDescGroups(uniqueGroups,totalPersons, typeName);
	    System.out.println();
		    for (int i=0 ; i < totalFrames ; i++){
			    System.out.println();
		    	System.out.print(i+";");
		    	for  (int j=0 ; j < totalPersons ; j++){
//		    		System.out.print(matrix[i][j]+";");
		    		int id=matrix[i][j];
		    		System.out.print(getDescriptionGroup( uniqueGroups, id,""+id, totalPersons, typeName));
		    		System.out.print(";");
	            }
		    }
		    System.out.println();
		 }	 

	 public  static void printAllFrames(String[][] matrix,int totalFrames,int totalPersons,Set uniqueGroups,int typeName) {
		    System.out.println();
			 printDescGroups(uniqueGroups,totalPersons, typeName);
		    System.out.println();
			    for (int i=0 ; i < totalFrames ; i++){
				    System.out.println();
			    	System.out.print(i+";");
			    	for  (int j=0 ; j < totalPersons ; j++){
//			    		System.out.print(matrix[i][j]+";");
			    		String temp=matrix[i][j];
			    		String[] temp1=temp.split("-");
			    		int id=Integer.parseInt( temp1[0] );
			    		System.out.print(getDescriptionGroup( uniqueGroups, id,matrix[i][j], totalPersons, typeName));
			    		System.out.print(";");
		            }
			    }
			    System.out.println();
			 }
	 
	 public  static void writeFile(String fileName,String header,String[][] matrix,int totalFrames,int totalPersons,Set uniqueGroups,int typeName) {
//		    System.out.println();
		    
//			 printDescGroups(uniqueGroups,totalPersons);
		 
		 try{
			  // Create file 
			  FileWriter fstream = new FileWriter(fileName);
			  BufferedWriter out = new BufferedWriter(fstream);
			  out.write(header+"\n");

			  for (int i=0 ; i < totalFrames ; i++){
				  if (i==136){
				    System.out.println();}
			    	out.write(i+";");
			    	for  (int j=0 ; j < totalPersons ; j++){
//			    		System.out.print(matrix[i][j]+";");
			    		String temp=matrix[i][j];
			    		String[] temp1=temp.split("-");
			    		int id=Integer.parseInt( temp1[0] );
			    		out.write(getDescriptionGroup( uniqueGroups, id,matrix[i][j], totalPersons, typeName));
			    		out.write(";");
		            }
			    	out.write("\n");	
			    }
			  out.close();
			  }catch (Exception e){//Catch exception if any
				  System.err.println("Error: " + e.getMessage());
			  }
		 
		 

/*		  out.write(temp[p]+",");
	  }
	  out.write(temp[p]+"\n");
 }
 //Close the input stream
 in.close();

}
//Close the output stream */
		 		
		 

			 }
	 
	     
	 public static void main(String[] args) {
		 Set uniqueGroups= new HashSet();
		 Set group= new HashSet();
		
		int totalFrames=6;
		int totalPersons=6;
        int matrix[][]=Groups.createIntMatrix(totalFrames,totalPersons);
        System.out.println(matrix.length);
        matrix[0][0]=-1;
        matrix[0][1]=-1;
        matrix[0][2]=-1;
        matrix[0][3]=-1;
        matrix[0][4]=-2;
        matrix[0][5]=-2;
        
        matrix[1][0]=0;
        matrix[1][1]=1;
        matrix[1][2]=0;
        matrix[1][3]=1;
        matrix[1][4]=-1;
        matrix[1][5]=-1;
        
        matrix[2][0]=0;
        matrix[2][1]=1;
        matrix[2][2]=0;
        matrix[2][3]=1;
        matrix[2][4]=-1;
        matrix[2][5]=-1;
        
        matrix[3][0]=0;
        matrix[3][1]=1;
        matrix[3][2]=0;
        matrix[3][3]=2;
        matrix[3][4]=-1;
        matrix[3][5]=-1;
       
        matrix[4][0]=0;
        matrix[4][1]=0;
        matrix[4][2]=1;
        matrix[4][3]=0;
        matrix[4][4]=1;
        matrix[4][5]=-1;
        
        matrix[5][0]=0;
        matrix[5][1]=1;
        matrix[5][2]=0;
        matrix[5][3]=2;
        matrix[5][4]=-1;
        matrix[5][5]=-1;
       
        printMatrix(matrix,totalFrames,totalPersons);
        
        uniqueGroups=findUniqueGroups(matrix,totalFrames);
        System.out.println(uniqueGroups);
        
        int [][] newMatrix=setIdGroups(matrix, uniqueGroups,totalFrames,totalPersons);
        printMatrix(newMatrix,totalFrames,totalPersons);
        
//        String[] c=createNames(totalPersons);
//         printAllFrames( newMatrix,totalFrames,totalPersons, uniqueGroups);
        
        System.out.println("******************");
                
 /*       Hashtable idGroupsDiff=initializeGroupsdiffId(uniqueGroups);
        Object[] all =uniqueGroups.toArray();
        idGroupsDiff=putGroupsdiffId(idGroupsDiff,all[1]);
        idGroupsDiff=putGroupsdiffId(idGroupsDiff,all[1]);
        printGroupsdiffId(idGroupsDiff);
        */

		int typeTranslation=2;
        String [][] matrixGroupsDiffId=Groups.setIdGroupsDiffId(newMatrix, uniqueGroups,totalFrames,totalPersons);
        printMatrix(matrixGroupsDiffId,totalFrames,totalPersons);
        printAllFrames(matrixGroupsDiffId,totalFrames,totalPersons, uniqueGroups,typeTranslation);
        		
	 }
		

}	 
	 
